//  -------------------- iSharePoint -------------------- //
// 
//  Company:	IT Complex, LLC
//  Project:	Smart.Common
//  File name:	Ipc.cs
//  Developer:	Solomatov Igor
//  Created:	15.04.2012
// 
//  -------------------- iSharePoint -------------------- //

using System;
using System.Collections;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Ipc;
using System.Security.Principal;

namespace Smart
{
	[Localizable(false)]
	public class Ipc
	{
		public static volatile bool ClientChannelConfigurated;

		static Ipc()
		{
		}

		[MethodImpl(MethodImplOptions.Synchronized)]
		public static bool ConfigureAsClient(string ipcPortName, string ipcObjName, Type ipcType)
		{
			bool res;

			try
			{
				if (!ClientChannelConfigurated)
				{
					var clientProperties = new Hashtable();

					clientProperties["name"] = string.Empty;
					clientProperties["timeout"] = 120000;
					clientProperties["retryCount"] = 1;
					clientProperties["connectionTimeout"] = 120000;

					var formatter = new BinaryClientFormatterSinkProvider();

					var clientChannel = new IpcClientChannel(clientProperties, formatter);

					ChannelServices.RegisterChannel(clientChannel, false);

					ClientChannelConfigurated = true;
				}

				var url = string.Format("ipc://{0}/{1}", ipcPortName, ipcObjName);

				RemotingConfiguration.RegisterWellKnownClientType(ipcType, url);

				H.LT("ConfigureAsClient portName: {0}, Url: {1}, Type: {2}", ipcPortName, url, ipcType.Name);

				res = true;
			}
			catch (Exception x)
			{
				H.LX("ConfigureAsClient", x);

				res = false;
			}

			return res;
		}

		[MethodImpl(MethodImplOptions.Synchronized)]
		public static bool ConfigureAsServer(string ipcPortName, string ipcObjName, Type ipcType)
		{
			bool res;

			try
			{
				var sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);

				var account = sid.Translate(typeof(NTAccount)) as NTAccount;

				if (account == null)
					return false;

				var serverProperties = new Hashtable();

				serverProperties["name"] = string.Empty;
				serverProperties["exclusiveAddressUse"] = true;
				serverProperties["portName"] = ipcPortName;
				serverProperties["authorizedGroup"] = account.Value;

				H.LT("ConfigureAsServer portName: {0}, authorizedGroup: {1}, Type: {2}", ipcPortName, account.Value, ipcType.Name);

				var formatter =
					new BinaryServerFormatterSinkProvider
						{
							TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full
						};

				var serverChannel = new IpcServerChannel(serverProperties, formatter);

				ChannelServices.RegisterChannel(serverChannel, false);

				RemotingConfiguration.RegisterWellKnownServiceType(ipcType, ipcObjName, WellKnownObjectMode.Singleton);

				var urls = serverChannel.GetUrlsForUri(ipcObjName);

				foreach (var url in urls)
					H.LT("ConfigureAsServer portName: {0} Url: {1}", ipcPortName, url);

				res = true;
			}
			catch (Exception x)
			{
				H.LI("ConfigureAsServer", x);

				res = false;
			}

			return res;
		}
	}
}